/*
* 本程序来自 上玄 开源 
* 个人空间 https://gitee.com/skyvippower
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>

#define MAX_NUM 100
//学生最大容纳量

typedef struct
{
    char no[30];
    char name[10];
    char sex[10];
	char phone[20];
	float cyuyan;
	float computer;
	float datastruct;
}*student,student1;

typedef struct
{
	student stu[MAX_NUM];
	int number;
}*studentDB;


void read(studentDB temp)
{
	FILE *infile;
    infile = fopen("./数据.txt","r");
	if (!infile)
	{
		printf("文件打开失败！");
		exit(0);
	}
	while (!feof(infile))
	{
        temp->stu[temp->number] = malloc(sizeof(student1));
        fscanf(infile,"%s %s %s %s %f %f %f",temp->stu[temp->number]->no,temp->stu[temp->number]->name,temp->stu[temp->number]->sex,temp->stu[temp->number]->phone,&(temp->stu[temp->number]->cyuyan),&(temp->stu[temp->number]->computer),&(temp->stu[temp->number]->datastruct));
        temp->number++;
	}
	fclose(infile);
    //printf("%d",temp->number);
}

void write(studentDB temp)
{
    FILE *outfile;
    outfile = fopen("./数据.txt", "w");
    if (!outfile)
    {
        printf("文件打开失败！");
        exit(1); //非零值表示错误
    }
    if (temp && temp->number > 0) // 检查指针是否有效
    {
        for (int i = 0; i < temp->number; i++)
        {
	        if(i == temp->number-1) {//判断是否为最后一排
				fprintf(outfile,"%s %s %s %s %.2f %.2f %.2f",temp->stu[i]->no,temp->stu[i]->name,temp->stu[i]->sex,temp->stu[i]->phone,temp->stu[i]->cyuyan,temp->stu[i]->computer,temp->stu[i]->datastruct);
			}
			else{
				fprintf(outfile,"%s %s %s %s %.2f %.2f %.2f\n",temp->stu[i]->no,temp->stu[i]->name,temp->stu[i]->sex,temp->stu[i]->phone,temp->stu[i]->cyuyan,temp->stu[i]->computer,temp->stu[i]->datastruct);
			}
		}
    }
    fclose(outfile);
    printf("保存成功");
	read(temp);
}

void display(studentDB temp)
{
    printf("|   学号   |姓名|性别|  手机号  |c语言|计算机系统|数据结构|\n");
    for (int i = 0; i < temp->number; i++)
	{
        printf("%s %s %s %s %.2f %.2f %.2f\n",temp->stu[i]->no,temp->stu[i]->name,temp->stu[i]->sex, temp->stu[i]->phone,temp->stu[i]->cyuyan,temp->stu[i]->computer,temp->stu[i]->datastruct);
	}
	
}

void menu()
{
	//printf("本程序来自 上玄 开源 个人空间 https://gitee.com/skyvippower");
	printf("\n\n\t****************************简单学生信息管理系统*****************************\n");
	printf("\t*                              1.显示学生信息                             *|\n");
	printf("\t*                              2.增加学生信息                             *|\n");
	printf("\t*                              3.删除学生信息                             *|\n");
	printf("\t*                              4.修改学生信息                             *|\n");
	printf("\t*                              5.查询学生信息                             *|\n");
    printf("\t*                              6.排序学生成绩                             *|\n");
    printf("\t*                              7.计算学生平均成绩                         *|\n");
    printf("\t*                              8.保存学生信息                             *|\n");
    printf("\t*                              9.统计全部课程及格人数                     *|\n");
    printf("\t*                              10.输出总成绩最高的学生信息                *|\n");
	printf("\t*                              0.退出系统                                 *|\n");
	printf("\t***************************************************************************\n");
	printf("请选择你的操作并将序号输入：");
}

int countDigits(long long n) {
	//计算位数的函数
    int count = 0;
    while (n > 0) {
        n /= 10; // 移除最右边的数字
        count++; // 位数增加
    }
    return count;
}

void insert(studentDB temp) //添加学生
{
    char no[30];
    printf("请输入要添加学生的学号：");
    scanf("%s",no);
    int n;
    long long num;
    sscanf(no,"%lld",&num);//将字符串转化为长整形
    n = countDigits(num);
    if (n != 11)
	{
        printf("输入的学号位数有误，请重新输入！");
        return;
	}
	else
	{
        student1 stu;
        FILE *outfile;
        outfile = fopen("./数据.txt","a");
        if (!outfile)
        {
            printf("文件打开失败！");
            exit(0);
        }
        strcpy(stu.no,no);
        printf("请输入姓名：");
        scanf("%s",stu.name);
        printf("请输入性别：");
        scanf("%s",stu.sex);
        printf("请输入手机号：");
        scanf("%s",stu.phone);
        printf("请输入c语言成绩(带小数点)：");
        scanf("%f",&stu.cyuyan);
        printf("请输入计算机系统成绩(带小数点)：");
        scanf("%f",&stu.computer);
        printf("请输入数据结构成绩(带小数点)：");
        scanf("%f",&stu.datastruct);
        n = fprintf(outfile,"\n%s %s %s %s %f %f %f",stu.no,stu.name,stu.sex,stu.phone,stu.cyuyan,stu.computer,stu.datastruct);
        printf("%s %s %s %s %.2f %.2f %.2f",stu.no,stu.name,stu.sex,stu.phone,stu.cyuyan,stu.computer,stu.datastruct);
        printf("学生信息已成功插入！信息长度：%d\n",n);
        fclose(outfile); // 关闭文件
		read(temp);
        return;
    }
}

void delete(studentDB temp)
{
	printf("请输入要删除的学生信息学号：");
	char no[15];
    scanf("%s",no);
    printf("%s",no);
    for (int i = 0; i < temp->number ; i++)
	{
        //printf("%s",temp->stu[i]->no);
        if (strcmp(temp->stu[i]->no,no) == 0)
		{
            for (int k = i; k < temp->number; k++)
			{
				temp->stu[k] = temp->stu[k + 1];
			}
			free(temp->stu[temp->number]);
			temp->number--;
			printf("学生信息已成功删除！\n");
			return;
		}
	}
    printf("学生学号输入错误！");
    return;
}

void modify(studentDB temp)
{
	printf("请输入要修改的学生信息学号：");
	char no[15];
    scanf("%s", no);
    long num;
    sscanf(no,"%ld",&num);
	int flag=0;
    for (int i = 0; i < temp->number ; i++)
	{
        if (strcmp(no,temp->stu[i]->no)==0)
		{
            printf("\n学号：%s  姓名：%s  性别：%s  手机号：%s  c语言：%.2f  计算机系统：%.2f  数据结构：%.2f\n\n\n", temp->stu[i]->no, temp->stu[i]->name, temp->stu[i]->sex, temp->stu[i]->phone, temp->stu[i]->cyuyan, temp->stu[i]->computer, temp->stu[i]->datastruct);
            printf("|1.学号|2.姓名|3.性别|4.手机号|5.c语言成绩|6.计算机系统成绩|7.数据结构成绩|8.不改动并返回菜单|9.依次修改全部数据\n\n\n请输入要改动的数据项：");
			scanf("%d",&flag);
			//switch判断
			switch(flag)
			{
				case 1:
					printf("请输入要修改的学号：");
					scanf("%s",temp->stu[i]->no);
					break;
				case 2:
					printf("请输入姓名：");
					scanf("%s",temp->stu[i]->name);
					break;
				case 3:
					printf("请输入性别：");
					scanf("%s",temp->stu[i]->sex);
					break;
				case 4:
					printf("请输入手机号：");
					scanf("%s",temp->stu[i]->phone);
					break;
				case 5:					
					printf("请输入c语言成绩(带小数点)：");
					scanf("%f",&(temp->stu[i]->cyuyan));	
					break;
				case 6:
					printf("请输入计算机系统成绩(带小数点)：");
					scanf("%f",&(temp->stu[i]->computer));
					break;
				case 7:
					printf("请输入数据结构成绩(带小数点)：");
					scanf("%f",&(temp->stu[i]->datastruct));
					break;
				case 8:
					return;
				case 9:
					printf("请输入姓名：");
					scanf("%s",temp->stu[i]->name);
					printf("请输入性别：");
					scanf("%s",temp->stu[i]->sex);
					printf("请输入手机号：");
					scanf("%s",temp->stu[i]->phone);
					printf("请输入c语言成绩(带小数点)：");
					scanf("%f",&(temp->stu[i]->cyuyan));
					printf("请输入计算机系统成绩(带小数点)：");
					scanf("%f",&(temp->stu[i]->computer));
					printf("请输入数据结构成绩(带小数点)：");
					scanf("%f",&(temp->stu[i]->datastruct));
					printf("学生信息已成功修改！\n");
					break;
				default:
					printf("请输入1-9的数字\n");
					return;
			}
			flag=1;
			return;
		}
	}
    if (flag == 0)
    {
        printf("学生学号输入错误！");
        return;
    }
	
}

void search(studentDB temp)
{
	printf("请输入要查询学生信息的方式，1为姓名查找，2为学号查找\n请选择：");
	int n;
	scanf("%d",&n);
	if (n==2)
	{
		printf("请输入要查询的学生学号：");
		char no[15];
		scanf("%s",no);
		for (int i = 0; i < temp->number; i++)
		{
			if (strcmp(temp->stu[i]->no,no) == 0)
			{
                printf("学号：%s  姓名：%s  性别：%s  手机号：%s  c语言：%.2f  计算机系统：%.2f  数据结构：%.2f\n", temp->stu[i]->no, temp->stu[i]->name, temp->stu[i]->sex, temp->stu[i]->phone, temp->stu[i]->cyuyan, temp->stu[i]->computer, temp->stu[i]->datastruct);
				return;
			}
		}
		printf("系统中未找到该学生信息！\n");
	}
	else if (n==1)
	{
		printf("请输入要查询的学生姓名：");
		char name[5];
		scanf("%s",name);
        //printf("%d",temp->number);
		for (int i = 0; i < temp->number; i++)
		{
			//比较name变量和temp->stu[i]->name
            //printf("%s",name);
            if (strcmp(temp->stu[i]->name,name) == 0)
			{
                printf("%s",temp->stu[i]->name);
                printf("学号：%s  姓名：%s  性别：%s  手机号：%s  c语言：%.2f  计算机系统：%.2f  数据结构：%.2f\n",temp->stu[i]->no, temp->stu[i]->name, temp->stu[i]->sex, temp->stu[i]->phone, temp->stu[i]->cyuyan, temp->stu[i]->computer, temp->stu[i]->datastruct);
				return;
			}
		}
		printf("系统中未找到该学生信息！\n");
        return;
	}
	else if (n==0)
	{
		return;
	}
	
	else
	{
		printf("请输入数字1或者2选择查询方式或者输入0返回菜单！");
        return;
	}
	
}

// 比较c语言成绩函，用于qsort  
int compare_cyuyan(const void *a, const void *b) {  
    student stuA = *(student *)a; 
    student stuB = *(student *)b; 
    return stuB->cyuyan - stuA->cyuyan; 
}
// 比较计算机函数，用于qsort  
int compare_computer(const void *a, const void *b) {  
    student stuA = *(student *)a; 
    student stuB = *(student *)b; 
    return stuB->computer - stuA->computer; 
}
//比较数据结构
int compare_datastruct(const void *a, const void *b) {  
    student stuA = *(student *)a;  
    student stuB = *(student *)b;  
    return stuB->datastruct - stuA->datastruct;  
}
// 三种方法排序学生
void sort_students_by_cyuyan(studentDB db) {  
    qsort(db->stu, db->number, sizeof(student), compare_cyuyan);  
}

void sort_students_by_computer(studentDB db) {  
    qsort(db->stu, db->number, sizeof(student), compare_computer);  
}

void sort_students_by_datastruct(studentDB db) {  
    qsort(db->stu, db->number, sizeof(student), compare_datastruct);  
}

void sort(studentDB temp)
{
	int n = 0;
	printf("|1.c语言成绩降序排列|2.计算机成绩降序排列|3.数据结构成绩降序排列|\n请选择排序方式：");
	scanf("%d",&n);
	switch (n)
	{
	case 1:
		sort_students_by_cyuyan(temp);// 对学生信息按c语言分数进行排序
		break;
	case 2:
		sort_students_by_computer(temp);
		break;
	case 3:
		sort_students_by_datastruct(temp);
		break;
	default:
		return;
	}

    // 输出排序后的学生信息
    for (int i = 0; i < temp->number; i++)
    {
        printf("%d. 学号：%s,姓名：%s,性别：%s,电话：%s,计算机成绩：%.2f,数据结构成绩：%.2f,c语言成绩：%.2f\n",i+1,temp->stu[i]->no, temp->stu[i]->name, temp->stu[i]->sex, temp->stu[i]->phone, temp->stu[i]->computer, temp->stu[i]->datastruct, temp->stu[i]->cyuyan);
    }
    return;
}

void avg(studentDB temp)
{
	float ctotal = 0.0;
	float computertotal = 0.0;
	float datastruttotal = 0.0;
	for (int i = 0; i < temp->number; i++)
	{
		ctotal += temp->stu[i]->cyuyan;
		computertotal += temp->stu[i]->computer;
		datastruttotal += temp->stu[i]->datastruct;
	}
	printf("c语言平均成绩：%.2f  计算机系统平均成绩：%.2f  数据结构平均成绩：%.2f",ctotal/temp->number,computertotal/temp->number,datastruttotal/temp->number);
	return;
}

void count(studentDB temp)
{
	int count = 0;
	printf("全部及格的同学如下：");
	for (int i = 0; i < temp->number; i++)
	{
		if (temp->stu[i]->cyuyan >= 60.0 && temp->stu[i]->computer >= 60.0 && temp->stu[i]->datastruct >= 60.0)
		{
			count++;
			printf("%s\t",temp->stu[i]->name);
		}
	}
	printf("\n全部课程及格人数：%d",count);
}

// 所有学生总分第一
void printTopStudent(studentDB temp) {  
    if (temp->number == 0) {  
        printf("数据库没有学生信息。\n");  
        return;  
    }  
  
    int topIndex = 0;
    float topScore = temp->stu[topIndex]->cyuyan + temp->stu[topIndex]->computer + temp->stu[topIndex]->datastruct;  
  
    // 遍历所有学生，找到总分最高的
    for (int i = 1; i < temp->number; i++) {  
        float currentScore = temp->stu[i]->cyuyan + temp->stu[i]->computer + temp->stu[i]->datastruct;  
        if (currentScore > topScore) {  
            topIndex = i;//如果总分更高就赋值给下标变量topIndex
            topScore = currentScore;  
        }  
    }  
    printf("总分最高的学生是：\n");  
    printf("学号：%s\n", temp->stu[topIndex]->no);  
    printf("姓名：%s\n", temp->stu[topIndex]->name);  
    printf("性别：%s\n", temp->stu[topIndex]->sex);  
    printf("电话：%s\n", temp->stu[topIndex]->phone);  
    printf("c语言成绩：%.2f\n", temp->stu[topIndex]->cyuyan);  
    printf("计算机成绩：%.2f\n", temp->stu[topIndex]->computer);  
    printf("数据结构成绩：%.2f\n", temp->stu[topIndex]->datastruct);  
    printf("总分：%.2f\n", topScore);  
}

int main()
{
    studentDB db = malloc(sizeof(*db));
 	db->number = 0;
	read(db);
    while(1){
        menu();
        int n;
        scanf("%d",&n);
		switch (n){
            case 1: display(db);break;//展示
            case 2: insert(db);break;//增加
			case 3: delete(db);break;//删除
			case 4: modify(db);break;//修改
			case 5: search(db);break;//查找
			case 6: sort(db);break;//学号排序
			case 7: avg(db);break;//平均分
			case 8: write(db);break;//保存
			case 9: count(db);break;//及格人数
			case 10: printTopStudent(db);break;//总分第一
			case 0:
				free(db);
				return 0;
			default: break;
		}
	}
 	free(db);
	return 0;
}
